package com.sxg.service.impl;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sxg.convert.SxgUserConvert;
import com.sxg.dao.SxgUserDao;
import com.sxg.entity.SxgUserEntity;
import com.sxg.query.SxgUserQuery;
import com.sxg.redis.RedisCache;
import com.sxg.security.pojo.LoginUser;
import com.sxg.security.service.TokenService;
import com.sxg.service.SxgFileService;
import com.sxg.service.SxgUserService;
import com.sxg.utils.SecurityUtils;
import com.sxg.utils.StringUtils;
import com.sxg.utils.code.AjaxResult;
import com.sxg.vo.SxgUserVO;
import com.sxg.vo.resp.ModifyPasswordReqVo;
import lombok.AllArgsConstructor;
import com.sxg.page.PageResult;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * 用户表
 *
 * @author 浪漫写尽歌谱 3298751420@qq.com
 * @since 1.0.0 2024-03-07
 */
@Service
@AllArgsConstructor
public class SxgUserServiceImpl extends ServiceImpl<SxgUserDao, SxgUserEntity> implements SxgUserService {

    @Resource
    private SxgFileService sxgFileService;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private RedisCache redisCache;

    @Resource
    private TokenService tokenService;

    @Override
    public PageResult<SxgUserVO> page(SxgUserQuery query) {
        IPage<SxgUserEntity> page = baseMapper.selectPage(PageResult.getPage(query), getWrapper(query));
        return new PageResult<>(SxgUserConvert.INSTANCE.convertList(page.getRecords()), page.getTotal());
    }

    @Override
    public List<SxgUserEntity> getUserList() {
        List<SxgUserEntity> userEntities = baseMapper.selectList(new QueryWrapper<>());
        return userEntities;
    }

    private LambdaQueryWrapper<SxgUserEntity> getWrapper(SxgUserQuery query) {
        LambdaQueryWrapper<SxgUserEntity> wrapper = Wrappers.lambdaQuery();
        return wrapper;
    }

    @Override
    public void save(SxgUserVO vo) {
        SxgUserEntity entity = SxgUserConvert.INSTANCE.convert(vo);

        baseMapper.insert(entity);
    }

    @Override
    public void update(SxgUserVO vo) {
        SxgUserEntity entity = SxgUserConvert.INSTANCE.convert(vo);

        updateById(entity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(List<Long> idList) {
        removeByIds(idList);
    }

    @Override
    public SxgUserEntity selectUserByUserName(Long username) {
        QueryWrapper<SxgUserEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(SxgUserEntity::getUserName, username);
        return baseMapper.selectOne(queryWrapper);
    }

    @Override
    public AjaxResult avatar(MultipartFile file) {
        //校验文件
        if (Objects.isNull(file) || file.isEmpty()) {
            return AjaxResult.error("文件不能为空");
        }
        String avatar = sxgFileService.uploadFile(file);
        Long userId = SecurityUtils.getUserId();
        SxgUserEntity sxgUserEntity = new SxgUserEntity();
        sxgUserEntity.setId(userId);
        sxgUserEntity.setAvatar(avatar);
        updateById(sxgUserEntity);
        redisCache.deleteObject("sxg:userInfo:" + SecurityUtils.getUserId());

        return AjaxResult.success().put("url", avatar);
    }

    @Override
    public AjaxResult updateInfo(SxgUserVO vo) {
        SxgUserEntity sxgUserEntity = new SxgUserEntity();
        sxgUserEntity.setId(SecurityUtils.getUserId());
        sxgUserEntity.setNickName(vo.getNickName());
        sxgUserEntity.setGender(vo.getGender());
        sxgUserEntity.setSignature(vo.getSignature());
        updateById(sxgUserEntity);

        //更新缓存
        LoginUser loginUser = SecurityUtils.getLoginUser();
        SxgUserEntity userEntity = loginUser.getSxgUserEntity();
        userEntity.setNickName(vo.getNickName());
        userEntity.setGender(vo.getGender());
        userEntity.setSignature(vo.getSignature());
        loginUser.setSxgUserEntity(userEntity);
        tokenService.verifyToken(loginUser);
        redisCache.deleteObject("sxg:userInfo:" + SecurityUtils.getUserId());
        return AjaxResult.success();
    }

    @Override
    public AjaxResult modifyPassword(ModifyPasswordReqVo vo) {
        Long userId = SecurityUtils.getUserId();
        SxgUserEntity sxgUserEntity = getById(userId);
        if (SecurityUtils.matchesPassword(sxgUserEntity.getPassword(), vo.getOldPassword())) {
            return AjaxResult.error("原密码不正确");
        }
        if (SecurityUtils.matchesPassword(sxgUserEntity.getPassword(), vo.getNewPassword())) {
            return AjaxResult.error("新密码不能与原密码相同");
        }
        sxgUserEntity.setPassword(SecurityUtils.encryptPassword(vo.getNewPassword()));
        updateById(sxgUserEntity);
        return AjaxResult.success();
    }

    @Override
    public SxgUserEntity selectUserByUserId(Long userId) {
        if (userId == null) {
            return null;
        }
        SxgUserEntity sxgUserEntity = null;
        String userJson = stringRedisTemplate.opsForValue().get("sxg:userInfo:" + userId);
        sxgUserEntity = JSON.parseObject(userJson, SxgUserEntity.class);
        if (StringUtils.isNull(userJson)) {
            sxgUserEntity = getById(userId);
            stringRedisTemplate.opsForValue().set("sxg:userInfo:" + userId, JSON.toJSONString(sxgUserEntity), 60 * 60 * 24, TimeUnit.SECONDS);
        } else {
            sxgUserEntity = JSON.parseObject(userJson, SxgUserEntity.class);
        }
        return sxgUserEntity;
    }

    @Override
    public SxgUserEntity getUserInfo() {
        // 获取当前登录用户并脱敏数据
        SxgUserEntity userEntity = SecurityUtils.getLoginUser().getSxgUserEntity();
        userEntity.setPassword(null);
        userEntity.setCreateTime(null);
        userEntity.setUpdateTime(null);
        return userEntity;
    }
}